package com.factory.common.shiro.filter;

import com.factory.common.model.SysUser;
import com.factory.common.service.UserService;
import com.factory.common.utils.ModelHelper;
import com.factory.common.utils.ReturnHelper;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Map;

public class LoginFilter extends PathMatchingFilter {
	@Autowired
	private UserService userService;
	 
    private String loginUrl = "/login.jsp";

    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        if(isLoginRequest(req)) {
            if("post".equalsIgnoreCase(req.getMethod())) {//form表单提交
                //已经登录过
                if(SecurityUtils.getSubject().isAuthenticated()) {
                    // 退出登陆
                    SecurityUtils.getSubject().logout();
                }
                String username = req.getParameter("username");
                String password = req.getParameter("password");
                try {
                    //5、委托给Realm进行登录
                    SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password));
                } catch (Exception e) {
                    e.printStackTrace();
                    onLoginFail(resp, e.getClass().getName()); //登录失败
                    return false;
                }
            }
            SysUser users=ModelHelper.getUser();
            if(users==null){
            	String username = req.getParameter("username");
            	SysUser user = userService.findByUsername(username);
                if(user == null) {
                    throw new UnknownAccountException();//没找到帐号
                }
                SecurityUtils.getSubject().getSession().setAttribute("userInfo", user);
            }
            System.out.println("============已经登录========="+users);
            return true;//继续过滤器链
        }else {
            if(SecurityUtils.getSubject().isAuthenticated()) {
                return true;//已经登录过
            } else {
                userNoLogin(resp);
                return false;
            }
        }
    }

    private void userNoLogin(HttpServletResponse httpResponse) throws IOException {
        httpResponse.setHeader("content-type", "text/html;charset=UTF-8");
        httpResponse.setStatus(HttpServletResponse.SC_OK);
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = ReturnHelper.getSimpleMap(5001, "尚未登陆");
        httpResponse.getWriter().append(mapper.writeValueAsString(map));
    }
    //登录失败返回错误信息
    private void onLoginFail(HttpServletResponse httpResponse, String exceptionClassName) throws IOException {
        httpResponse.setStatus(HttpServletResponse.SC_OK);
        httpResponse.setHeader("content-type", "text/html;charset=UTF-8");
        ObjectMapper mapper = new ObjectMapper();
        String error = null;
        if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if(exceptionClassName != null) {
            error = "其他错误：" + exceptionClassName;
        }
        Map<String, Object> map = ReturnHelper.getSimpleMap(200, error);
        httpResponse.getWriter().append(mapper.writeValueAsString(map));
    	SecurityUtils.getSubject().logout();
    }

    private boolean isLoginRequest(HttpServletRequest req) {
        return pathsMatch(loginUrl, WebUtils.getPathWithinApplication(req));
    }


    public String getLoginUrl() {
        return loginUrl;
    }

    public void setLoginUrl(String loginUrl) {
        this.loginUrl = loginUrl;
    }
}
